package com.qingcheng.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.qingcheng.dao.OrderConfigMapper;
import com.qingcheng.dao.OrderItemMapper;
import com.qingcheng.dao.OrderLogMapper;
import com.qingcheng.dao.OrderMapper;
import com.qingcheng.entity.PageResult;
import com.qingcheng.entity.SplitResult;
import com.qingcheng.pojo.order.*;
import com.qingcheng.pojo.user.Address;
import com.qingcheng.service.goods.SkuService;
import com.qingcheng.service.order.CartService;
import com.qingcheng.service.order.OrderService;
import com.qingcheng.util.CacheKey;
import com.qingcheng.util.IdWorker;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service(interfaceClass = OrderService.class)
@Transactional
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private OrderLogMapper orderLogMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private OrderConfigMapper orderConfigMapper;
    @Reference
    private SkuService skuService;
    @Autowired
    private CartService cartService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 返回全部记录
     *
     * @return
     */
    public List<Order> findAll() {
        return orderMapper.selectAll();
    }

    /**
     * 分页查询
     *
     * @param page 页码
     * @param size 每页记录数
     * @return 分页结果
     */
    public PageResult<Order> findPage(int page, int size) {
        PageHelper.startPage(page, size);
        Page<Order> orders = (Page<Order>) orderMapper.selectAll();
        return new PageResult<Order>(orders.getTotal(), orders.getResult());
    }

    /**
     * 条件查询
     *
     * @param searchMap 查询条件
     * @return
     */
    public List<Order> findList(Map<String, Object> searchMap) {
        Example example = createExample(searchMap);
        return orderMapper.selectByExample(example);
    }

    /**
     * 分页+条件查询
     *
     * @param searchMap
     * @param page
     * @param size
     * @return
     */
    public PageResult<Order> findPage(Map<String, Object> searchMap, int page, int size) {
        PageHelper.startPage(page, size);
        Example example = createExample(searchMap);
        Page<Order> orders = (Page<Order>) orderMapper.selectByExample(example);
        return new PageResult<Order>(orders.getTotal(), orders.getResult());
    }

    /**
     * 根据Id查询
     *
     * @param id
     * @return
     */
    public Order findById(String id) {
        return orderMapper.selectByPrimaryKey(id);
    }

    /**
     * 新增
     *
     * @param order
     */
    public void add(Order order) {
        orderMapper.insert(order);
    }

    /**
     * 修改
     *
     * @param order
     */
    public void update(Order order) {
        orderMapper.updateByPrimaryKeySelective(order);
    }

    /**
     * 删除
     *
     * @param id
     */
    public void delete(String id) {
        orderMapper.deleteByPrimaryKey(id);
    }

    /**
     * 通过order的id查找order和orderItem信息
     *
     * @param id
     * @return
     */
    @Override
    public Orders findOrderById(String id) {
        Orders orders = new Orders();
        Order order = orderMapper.selectByPrimaryKey(id);
        orders.setOrder(order);
        Example example = new Example(OrderItem.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("orderId", id);
        List<OrderItem> orderItemList = orderItemMapper.selectByExample(example);
        orders.setOrderItemList(orderItemList);
        return orders;
    }

    /**
     * 批量发货
     *
     * @param orderList
     * @return
     */
    @Override
    public int sendBatch(List<Order> orderList) {
        int count = 0;
        OrderLog orderLog = new OrderLog();
        for (Order order : orderList) {
            if (order.getShippingCode() == null || order.getShippingName() == null) {
                throw new RuntimeException("请填写快递公司和快递单号！");
            }
            order.setOrderStatus("3");
            order.setConsignStatus("2");
            order.setConsignTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
            count++;
            orderLog.setOrderId(order.getId());
            orderLog.setId(idWorker.nextId() + "");
            orderLog.setConsignStatus("2");
            orderLog.setOperateTime(new Date());
            orderLog.setOrderStatus("3");
            orderLog.setPayStatus(order.getPayStatus());
            orderLog.setRemarks("正常发货");
            orderLogMapper.insertSelective(orderLog);
        }
        return count;
    }

    /**
     * 订单超时未付款自动取消
     */
    @Override
    public void orderTimeoutLogic() {
        System.out.println(1);
        //获取超时时间
        OrderConfig orderConfig = orderConfigMapper.selectByPrimaryKey(1);
        Integer orderTimeout = orderConfig.getOrderTimeout();
        LocalDateTime localDateTime = LocalDateTime.now().minusMinutes(orderTimeout);

        System.out.println(2);
        Example example = new Example(Order.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLessThan("createTime", localDateTime);//已经超时 的订单
        criteria.andEqualTo("orderStatus", "0");//未付款的订单
        criteria.andEqualTo("isDelete", "0");//没有删除的订单
        List<Order> orders = orderMapper.selectByExample(example);

        for (Order order : orders) {

            //更新订单状态
            order.setCloseTime(new Date());//设置订单关闭时间
            order.setOrderStatus("4");//设置订单状态为关闭
            orderMapper.updateByPrimaryKeySelective(order);

            //添加日志
            OrderLog orderLog = new OrderLog();
            orderLog.setId(idWorker.nextId() + "");//设置日志id
            orderLog.setOrderId(order.getId());//设置订单id
            orderLog.setPayStatus(order.getPayStatus());//设置支付状态
            orderLog.setOrderStatus(order.getOrderStatus());//设置订单状态
            orderLog.setOperateTime(order.getCloseTime());//设置操作时间
            orderLog.setOperater("admin");//设置管理员
            orderLog.setRemarks("订单支付超时，系统自动取消");//设置取消原因
            orderLogMapper.insert(orderLog);
        }

    }

    /**
     * 合并订单
     *
     * @param order1
     * @param order2
     */
    @Override
    public void merge(String order1, String order2) {

        Orders orders1 = findOrderById(order1);//主订单和主订单详情
        Orders orders2 = findOrderById(order2);//副订单和副订单详情
        Order mainOrder = orders1.getOrder();//主订单
        Order subOrder = orders2.getOrder();//副订单
        mainOrder.setTotalMoney(mainOrder.getTotalMoney() + subOrder.getTotalMoney());//设置主订单总金额
        mainOrder.setTotalNum(mainOrder.getTotalNum() + subOrder.getTotalNum());//设置主订单数量
        mainOrder.setPayMoney(mainOrder.getPayMoney() + subOrder.getPayMoney());//设置主订单付款金额
        mainOrder.setPreMoney(mainOrder.getPreMoney() + subOrder.getPreMoney());//设置主订单预付款金额
        mainOrder.setUpdateTime(new Date());//设置更新日期

        List<OrderItem> mainItemList = orders1.getOrderItemList();//获取主订单详情的集合
        List<OrderItem> subItemList = orders2.getOrderItemList();//获取副订单详情集合

        //将集合变为可读写集合
        CopyOnWriteArrayList<OrderItem> calMain = new CopyOnWriteArrayList<>(mainItemList);
        CopyOnWriteArrayList<OrderItem> calSub = new CopyOnWriteArrayList<>(subItemList);

        //遍历两个集合，如果主订单详情中的skuId=副订单详情中的skuId，将副订单详情中的数量合并到主订单中
        for (OrderItem mainItem : calMain) {
            for (OrderItem subItem : calSub) {
                if (mainItem.getSkuId().equals(subItem.getSkuId())) {
                    mainItem.setMoney(mainItem.getMoney() + subItem.getMoney());//设置主订单详情金额
                    mainItem.setNum(mainItem.getNum() + subItem.getNum());//设置主订单商品数量
                    mainItem.setPayMoney(mainItem.getPayMoney() + subItem.getPayMoney());//设置主订单付款金额
                    orderItemMapper.updateByPrimaryKeySelective(mainItem);//更新主订单详情
                    calSub.remove(subItem);//将相同订单从集合中移除
                    break;
                }
            }
        }

        if (calSub.size()>=1){
            for (OrderItem orderItem : calSub) {
                orderItem.setOrderId(mainOrder.getId());
                orderItemMapper.insertSelective(orderItem);
            }
        }



    }

    /**
     * 拆分订单的方法
     *
     * @param SplitResult
     */
    @Override
    public void split(List<SplitResult> SplitResult) {
        String id1 = SplitResult.get(0).getId();
        Integer num1 = SplitResult.get(0).getNum();
        if (num1 == 1) {
            throw new RuntimeException("子订单数量为1，不能拆分");
        }
        Integer num2 = SplitResult.get(1).getNum();
        if (num1 < num2) {
            throw new RuntimeException("拆分订单数量不得大于订单总数");
        }
        Order order1 = orderMapper.selectByPrimaryKey(id1);

//        Example example = new Example(OrderItem.class);
//        Example.Criteria criteria = example.createCriteria();
//        criteria.andEqualTo("orderId", id1);
//        List<OrderItem> orderItemList = orderItemMapper.selectByExample(example);

        Order order2 = order1;
        order1.setTotalNum(num1 - num2);
        order2.setTotalNum(num2);
        order2.setPayMoney(order1.getPayMoney() * num2 / num1);
        order1.setPayMoney(order1.getPayMoney() - order2.getPayMoney());
        order2.setTotalMoney(order1.getTotalMoney() * num2 / num1);
        order1.setTotalMoney(order1.getTotalMoney() - order2.getTotalMoney());
        order2.setCreateTime(new Date());
        order2.setUpdateTime(new Date());

//        order2.setId(idWorker.nextId() + "");
//        for (int i = 0; i < num2; i++) {
//            orderItemList.get(i).setOrderId(order2.getId());
//        }

        orderMapper.updateByPrimaryKeySelective(order1);
        orderMapper.insert(order2);
    }

    /**
     * 创建订单
     * @param order
     * @return
     */
    @Override
    @Transactional
    public Map<String, String> saveOrder(Order order) {
        List<Map<String, Object>> cartList = cartService.findNewOrderList(order.getUsername());//刷新最新价格
        //获取选中的购物车
        List<OrderItem> orderItemList = cartList.stream()
                .filter(cart -> (boolean) cart.get("checked"))
                .map(cart -> (OrderItem) cart.get("item"))
                .collect(Collectors.toList());
        //修改库存以及销量
        if (!skuService.deductionStock(orderItemList)){
            throw new RuntimeException("库存修改失败");
        };

        try {
            order.setId(idWorker.nextId()+"");
            IntStream intNum = orderItemList.stream().mapToInt(OrderItem::getNum);//订单数量
            order.setTotalNum(intNum.sum());
            IntStream intMoney = orderItemList.stream().mapToInt(OrderItem::getMoney);//订单总金额
            order.setTotalMoney(intMoney.sum());
            int preMoney = cartService.preferential(order.getUsername());//优惠金额
            order.setPreMoney(preMoney);
            order.setPayMoney(order.getTotalMoney()-order.getPreMoney());//支付金额
            order.setCreateTime(new Date());//order createTime
            order.setIsDelete("0");//delete status
            order.setConsignStatus("0");//shipping status
            order.setPayStatus("0");//pay status
            order.setOrderStatus("0");//order status
            orderMapper.insert(order);//insert into database

            double proportion = preMoney*1.0/order.getTotalMoney();
            for (OrderItem orderItem : orderItemList) {

                orderItem.setId(idWorker.nextId()+"");//create id
                orderItem.setPayMoney((int)(orderItem.getMoney()*proportion));//set payMoney
                orderItem.setOrderId(order.getId());
                orderItemMapper.insert(orderItem);//save to database
//                int i = 1/0;

                //订单创建成功之后向rabbit消息队列存入orderId,查询超时未支付的订单
                rabbitTemplate.convertAndSend("","queue.order",order.getId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            rabbitTemplate.convertAndSend("","queue.skuback", JSON.toJSONString(orderItemList));
            throw new RuntimeException("订单创建失败！");
        }

        cartService.deleteCheckedCart(order.getUsername());//update redis

        Map map = new HashMap();
        map.put("id",order.getId());
        map.put("payMoney",order.getPayMoney());
        System.out.println(map);
        return map;
    }

    /**
     * 修改订单支付状态
     * @param orderId
     * @param transactionId
     */
    @Override
    public void updateOrderStatus(String orderId, String transactionId) {

        Order order = orderMapper.selectByPrimaryKey(orderId);
        if ("0".equals(order.getPayStatus())&&order!=null){//订单不为空并且订单为未支付状态
            order.setPayStatus("1");
            order.setOrderStatus("1");
            order.setUpdateTime(new Date());
            order.setPayTime(new Date());
            order.setTransactionId(transactionId);//微信支付流水号
            orderMapper.updateByPrimaryKeySelective(order);//更新订单

            //记录订单变更日志
            OrderLog orderLog = new OrderLog();
            orderLog.setId(idWorker.nextId()+"");
            orderLog.setOrderId(orderId);
            orderLog.setOperateTime(new Date());
            orderLog.setOrderStatus("1");
            orderLog.setPayStatus("1");
            orderLog.setRemarks("支付流水号："+transactionId);
            orderLog.setOperater("system");
            orderLogMapper.insert(orderLog);//插入记录
        }
    }

    /**
     * 构建查询条件
     *
     * @param searchMap
     * @return
     */
    private Example createExample(Map<String, Object> searchMap) {
        Example example = new Example(Order.class);
        Example.Criteria criteria = example.createCriteria();
        if (searchMap != null) {
            // 订单id
            if (searchMap.get("id") != null && !"".equals(searchMap.get("id"))) {
                criteria.andLike("id", "%" + searchMap.get("id") + "%");
            }
            // 支付类型，1、在线支付、0 货到付款
            if (searchMap.get("payType") != null && !"".equals(searchMap.get("payType"))) {
                criteria.andLike("payType", "%" + searchMap.get("payType") + "%");
            }
            // 物流名称
            if (searchMap.get("shippingName") != null && !"".equals(searchMap.get("shippingName"))) {
                criteria.andLike("shippingName", "%" + searchMap.get("shippingName") + "%");
            }
            // 物流单号
            if (searchMap.get("shippingCode") != null && !"".equals(searchMap.get("shippingCode"))) {
                criteria.andLike("shippingCode", "%" + searchMap.get("shippingCode") + "%");
            }
            // 用户名称
            if (searchMap.get("username") != null && !"".equals(searchMap.get("username"))) {
                criteria.andLike("username", "%" + searchMap.get("username") + "%");
            }
            // 买家留言
            if (searchMap.get("buyerMessage") != null && !"".equals(searchMap.get("buyerMessage"))) {
                criteria.andLike("buyerMessage", "%" + searchMap.get("buyerMessage") + "%");
            }
            // 是否评价
            if (searchMap.get("buyerRate") != null && !"".equals(searchMap.get("buyerRate"))) {
                criteria.andLike("buyerRate", "%" + searchMap.get("buyerRate") + "%");
            }
            // 收货人
            if (searchMap.get("receiverContact") != null && !"".equals(searchMap.get("receiverContact"))) {
                criteria.andLike("receiverContact", "%" + searchMap.get("receiverContact") + "%");
            }
            // 收货人手机
            if (searchMap.get("receiverMobile") != null && !"".equals(searchMap.get("receiverMobile"))) {
                criteria.andLike("receiverMobile", "%" + searchMap.get("receiverMobile") + "%");
            }
            // 收货人地址
            if (searchMap.get("receiverAddress") != null && !"".equals(searchMap.get("receiverAddress"))) {
                criteria.andLike("receiverAddress", "%" + searchMap.get("receiverAddress") + "%");
            }
            // 订单来源：1:web，2：app，3：微信公众号，4：微信小程序  5 H5手机页面
            if (searchMap.get("sourceType") != null && !"".equals(searchMap.get("sourceType"))) {
                criteria.andLike("sourceType", "%" + searchMap.get("sourceType") + "%");
            }
            // 交易流水号
            if (searchMap.get("transactionId") != null && !"".equals(searchMap.get("transactionId"))) {
                criteria.andLike("transactionId", "%" + searchMap.get("transactionId") + "%");
            }
            // 订单状态
            if (searchMap.get("orderStatus") != null && !"".equals(searchMap.get("orderStatus"))) {
                criteria.andLike("orderStatus", "%" + searchMap.get("orderStatus") + "%");
            }
            // 支付状态
            if (searchMap.get("payStatus") != null && !"".equals(searchMap.get("payStatus"))) {
                criteria.andLike("payStatus", "%" + searchMap.get("payStatus") + "%");
            }
            // 发货状态
            if (searchMap.get("consignStatus") != null && !"".equals(searchMap.get("consignStatus"))) {
                criteria.andLike("consignStatus", "%" + searchMap.get("consignStatus") + "%");
            }
            // 是否删除
            if (searchMap.get("isDelete") != null && !"".equals(searchMap.get("isDelete"))) {
                criteria.andLike("isDelete", "%" + searchMap.get("isDelete") + "%");
            }

            // 数量合计
            if (searchMap.get("totalNum") != null) {
                criteria.andEqualTo("totalNum", searchMap.get("totalNum"));
            }
            // 金额合计
            if (searchMap.get("totalMoney") != null) {
                criteria.andEqualTo("totalMoney", searchMap.get("totalMoney"));
            }
            // 优惠金额
            if (searchMap.get("preMoney") != null) {
                criteria.andEqualTo("preMoney", searchMap.get("preMoney"));
            }
            // 邮费
            if (searchMap.get("postFee") != null) {
                criteria.andEqualTo("postFee", searchMap.get("postFee"));
            }
            // 实付金额
            if (searchMap.get("payMoney") != null) {
                criteria.andEqualTo("payMoney", searchMap.get("payMoney"));
            }
            //批量发货
            if (searchMap.get("ids") != null) {
                String[] ids = JSON.parseObject(searchMap.get("ids").toString(), String[].class);
                criteria.andIn("id", Arrays.asList(ids));
            }
        }
        return example;
    }

}
